/*
 * @author Anthony Knopp (amk9445@rit.edu)
 * @author Ian Tewksbury (ict8574@rit.edu)
 * 
 * This class is used to represent a configuration of a Checkers board. It is a 2D byte array consisting of:
 * 0 = Empty Space 
 * 1 = Player 1 Standard Checker
 * 2 = Player 2 Standard Checker
 * 3 = Player 1 King
 * 4 = Player 2 King
 * This class also is used as nodes within the tree.
 */
package edu.rit.checkers;
import java.util.ArrayList;

public class Config {
	
	// Class Variables
	private byte[][] internalConfig;
	private int player;
	int finalConfig;
	
	//Constructor that creates a Config object from a 2D byte array, and current player.
	public Config(byte[][] config, int player) {
		internalConfig = config;
		this.player = player;
		finalConfig = -1;
	}
	
	//Starting default checkers configuration, used to start the tree traversal.
	public Config(){
		player = 2;
		internalConfig = new byte[][] {
				{0,1,0,1,0,1,0,1},
				{1,0,1,0,1,0,1,0},
				{0,1,0,1,0,1,0,1},
				{0,0,0,0,0,0,0,0},
				{0,0,0,0,0,0,0,0},
				{2,0,2,0,2,0,2,0},
				{0,2,0,2,0,2,0,2},
				{2,0,2,0,2,0,2,0},
		};
		finalConfig = -1;
	}
	
	public byte[][] getConfig() {
		return internalConfig;
	}
	
	public int getPlayer() {
		return player;
	}
	
	/*
	 * Function to check if all pieces on the board are of one players.(winning configuration)
	 * I had to use an integer instead of a boolean as the class variable because there is no way to check to see if a boolean
	 *  has been set yet. Only calculates if finalConfig is equal to -1.
	 */
	public boolean isFinalConfig(){

		if(finalConfig != -1){
			if(finalConfig == 0){
				return false;
			}
			return true;
		}
		
		boolean playerOne = false;
	    boolean playerTwo = false;
		
		for(int r = 0; r < internalConfig.length; r++){
			for(int c = 0; c < internalConfig[r].length;c++){
				if(internalConfig[r][c] == 1 || internalConfig[r][c] == 3){
					playerOne = true;
				} else if(internalConfig[r][c] == 2 || internalConfig[r][c] == 4){
					playerTwo = true;
				}
			}
		}
		
		if(playerOne && playerTwo){
			finalConfig = 0;
			return false;
		}
		
		finalConfig = 1;
		return true;
	}
	
	/*
	 * Scoring method used as our heuristic for Alpha-Beta pruning. It counts the number of standard pieces and kings for each player and returns
	 * the difference of the two. (currentPlayerScore - opponentScore)
	 */
	public int getScore(){
		int pscore = 0;
		int oscore = 0;

		for(int r = 0; r < internalConfig.length; r++){
			for(int c =0; c < internalConfig[r].length; c++){
				if(internalConfig[r][c] == 1){
					pscore+=1;
				}
				if(internalConfig[r][c] == 3){
					pscore+=2;
				}
				
				if(internalConfig[r][c] == 2 ){
					oscore+=1;
				}
				if(internalConfig[r][c] == 4){
					oscore+=2;
			}
				
			}
		}
		
		return (pscore - oscore);
	}
	
	public String toString(){
		String retStr = "";
		
		for(int r = 0; r < internalConfig.length; r++){
			for(int c = 0; c < internalConfig[r].length;c++){
				retStr += internalConfig[r][c] + " ";
			}
			retStr += '\n';
		}
		
		
	
		return retStr;
	}
	

	/*
	 * This method returns a list of neighbors of the Config object that it is called on. These configs are created by
	 * first scanning the board for pieces of the current player to move. If any jumps are possible from these pieces then slides are not checked since 
	 * jumps have to be performed if possible by Checkers standard rule set. The board is then re-scanned for jumps or slides and a list of "moves" are created
	 * which are then converted to many different configurations and returned in an arrayList.
	 */
	public ArrayList<Config> getNextConfigs(){
		byte whosTurn;
		boolean jumpsPossible = false;
		ArrayList<Config> configList = new ArrayList<Config>();
		
		if(player == 1){
			whosTurn = 2; 
		} else {
			whosTurn = 1;
		}

		
		jumpsPossible = checkPossibleJumps(whosTurn);
		
		// If jumps are possible, then calculate jumps. If jumps are not possible then only calculate moves.
		if(jumpsPossible){
			for(int r = 0; r < internalConfig.length; r++){
				for(int c = 0; c < internalConfig[r].length; c++){
					
					if( internalConfig[r][c] == whosTurn || internalConfig[r][c] == whosTurn + 2 ){
						ArrayList<Move> jMoves = checkJumps(r,c,whosTurn);
						if(jMoves.size() != 0){
							for(Move mc: jMoves){
								configList.add(convertMoveToConfig(mc,whosTurn));
							}
				
						}
		
					}

				}
				
			}
		 }else{
			for(int r = 0; r < internalConfig.length; r++){
				for(int c = 0; c < internalConfig[r].length; c++){
					
					if( internalConfig[r][c] == whosTurn || internalConfig[r][c] == whosTurn + 2){
						ArrayList<Move> moves = checkMoves(r,c,whosTurn);
						if(moves.size() != 0){
							for(Move mc : moves){
								configList.add(convertMoveToConfig(mc,whosTurn));
							}
						}
					}
					
				}	
			}

		}

		return configList;
	}
	
	
	// This helper method scans the board looking for a possible jump for the current player moving. If it find a possible jump, it stops and returns true.
	private boolean checkPossibleJumps(byte whosTurn){
		
		int size = internalConfig.length;
		int oppoKing = -1;
		for(int r = 0; r < size; r++){
			for(int c = 0; c < size; c++){
				
				if(internalConfig[r][c] == whosTurn){
					
					if(internalConfig[r][c] == 3){
						oppoKing = 4;
					} else if (internalConfig[r][c] == 4){
						oppoKing = 3;
					}

					//If you're a king of either type.
					if(oppoKing != -1){
					
						//Check if valid move, not outside grid.
						if( ( ((r+1) < size) && ((r+2) < size) ) && ( ((c+1) < size) && ((c+2) < size)) ){
							if( ((internalConfig[r+1][c+1] == player || internalConfig[r+1][c+1] == oppoKing) && internalConfig[r+2][c+2] == 0) ){
								return true;
							}
						}
						
						//Check other direction
						if(	((c-1) >= 0) && ((c-2) >= 0) && ( ((r+1) < size) && ((r+2) < size)) ){
							
							if( ((internalConfig[r+1][c-1] == player || internalConfig[r+1][c-1] == oppoKing) && internalConfig[r+2][c-2] == 0) ){
								return true;

							}
						}
						
						
						if( ( ((c+1) < size) && ((c+2) < size) ) && ( ((r-1) >= 0) && ((r-2) >= 0)) ){
							
							if( ((internalConfig[r-1][c+1] == player || internalConfig[r-1][c+1] == oppoKing) && internalConfig[r-2][c+2] == 0) ){
								return true;
							}
						}
							
						if( ( ((r-1) >= 0) && ((r-2) >= 0) ) && ( ((c-1) >= 0) && ((c-2) >= 0)) ){
							
							if( ((internalConfig[r-1][c-1] == player  || internalConfig[r-1][c-1] == oppoKing) && internalConfig[r-2][c-2] == 0) ){
								return true;
							}
						}
						
					}else {

						//Add to columns if whosTurn == 1
						if(whosTurn == 1){
							
								//Check if valid move, not outside grid.
								if( ( ((r+1) < size) && ((r+2) < size) ) && ( ((c+1) < size) && ((c+2) < size)) ){
									if( ((internalConfig[r+1][c+1] == player || internalConfig[r+1][c+1] == oppoKing) && internalConfig[r+2][c+2] == 0) ){
										return true;
									}
								}
								
								//Check other direction
								if(	((c-1) >= 0) && ((c-2) >= 0) && ( ((r+1) < size) && ((r+2) < size)) ){
									if(((internalConfig[r+1][c-1] == player || internalConfig[r+1][c-1] == oppoKing) && internalConfig[r+2][c-2] == 0)){
										return true;
									}
								}
							
						}
				
						//Subtract from columns if whosTurn == 2
						if(whosTurn == 2){
							
							//Check if valid move, not outside grid.
				
							if( ( ((c+1) < size) && ((c+2) < size) ) && ( ((r-1) >= 0) && ((r-2) >= 0)) ){
								
								if( ((internalConfig[r-1][c+1] == player || internalConfig[r-1][c+1] == 3) && internalConfig[r-2][c+2] == 0) ){
									return true;
									
								}
							}
								
							if( ( ((r-1) >= 0) && ((r-2) >= 0) ) && ( ((c-1) >= 0) && ((c-2) >= 0)) ){
								
								if( ((internalConfig[r-1][c-1] == player || internalConfig[r-1][c-1] == 3)&& internalConfig[r-2][c-2] == 0) ){
									return true;
								
								}
							}
						}
					}
				}
			}
		}
		return false;
	}
	
	private Config convertMoveToConfig(Move m, byte whosTurn) {
		int size  = internalConfig.length;
		byte[][] newInternalConfig = new byte[8][8];
		Config config;
		ArrayList<Move> moveList = m.getMoveList();
		for(int i = 0; i < size; i++){
			for(int j =0 ; j < size; j++){
				newInternalConfig[i][j] = internalConfig[i][j];
			}
		}
		
		//If move list is a single move, simple swap, otherwise jumps and such
		byte piece = newInternalConfig[m.getSRow()][m.getSCol()];
		if(m.isJump = false){ //Just a move
			newInternalConfig[m.getSRow()][m.getSCol()] = 0;
			//Check to see if piece should be Kinged
			if(piece == 1 && m.getERow() == size-1){
				newInternalConfig[m.getERow()][m.getECol()] = 3;
			} else if (piece == 2 && m.getERow() == 0){
				newInternalConfig[m.getERow()][m.getECol()] = 4;
			}else {
				newInternalConfig[m.getERow()][m.getECol()] = piece;
			}
		} else if(moveList.size() == 0){	//single jump
			newInternalConfig[m.getSRow()][m.getSCol()] = 0;
			
			if(piece == 1 && m.getERow() == size-1){
				newInternalConfig[m.getERow()][m.getECol()] = 3;
			} else if (piece == 2 && m.getERow() == 0){
				newInternalConfig[m.getERow()][m.getECol()] = 4;
			}else {
				newInternalConfig[m.getERow()][m.getECol()] = piece;
			}
			
			newInternalConfig[m.getJRow()][m.getJCol()] = 0;
		} else{ //multiple jumps
			newInternalConfig[m.getSRow()][m.getSCol()] = 0;
			if(piece == 1 && m.getERow() == size-1){
				newInternalConfig[m.getERow()][m.getECol()] = 3;
			} else if (piece == 2 && m.getERow() == 0){
				newInternalConfig[m.getERow()][m.getECol()] = 4;
			}else {
				newInternalConfig[m.getERow()][m.getECol()] = piece;
			}

			newInternalConfig[m.getJRow()][m.getJCol()] = 0;
			for(Move rMoves : moveList){
				newInternalConfig[rMoves.getSRow()][rMoves.getSCol()] = 0;
				if(piece == 1 && rMoves.getERow() == size-1){
					newInternalConfig[rMoves.getERow()][rMoves.getECol()] = 3;
				} else if (piece == 2 && rMoves.getERow() == 0){
					newInternalConfig[rMoves.getERow()][rMoves.getECol()] = 4;
				}else {
					newInternalConfig[rMoves.getERow()][rMoves.getECol()] = piece;
				}
				newInternalConfig[rMoves.getJRow()][rMoves.getJCol()] = 0;
				
			}
		}
		
		config = new Config(newInternalConfig,whosTurn);
		return config;
	}

	private ArrayList<Move> checkMoves(int r, int c, byte whosTurn){
		int size = internalConfig.length;
		ArrayList<Move> moves = new ArrayList<Move>();

		if(internalConfig[r][c] == 3 || internalConfig[r][c] == 4){
			
			//Check if valid move, not outside grid.
			if( ((r+1) < size)  && (c+1) < size ){
				
				if( internalConfig[r+1][c+1] == 0){
					moves.add(new Move(r,c,r+1,c+1,false));
				}
				
			}
			
			if( ((r+1) < size)  && (c-1) >= 0 ){
				
				if( internalConfig[r+1][c-1] == 0){
					moves.add(new Move(r,c,r+1,c-1,false));

				}
				
			}
			
			
			//Check if valid move, not outside grid.
			if( ((r-1) >= 0)  && (c+1)  < size ){
				
				if( internalConfig[r-1][c+1] == 0){
					moves.add(new  Move(r,c,r-1,c+1,false));
				}
				
			}
			
			if( ((r-1) >= 0)  && (c-1)  >= 0){
				
				if( internalConfig[r-1][c-1] == 0){
					moves.add(new Move(r,c,r-1,c-1,false));
				}
				
			}

		} else { 
		
		
			if(whosTurn == 1){
				
				//Check if valid move, not outside grid.
				if( ((r+1) < size)  && (c+1) < size ){
					
					if( internalConfig[r+1][c+1] == 0){
						moves.add(new Move(r,c,r+1,c+1,false));
					}
					
				}
				
				if( ((r+1) < size)  && (c-1) >= 0 ){
					
					if( internalConfig[r+1][c-1] == 0){
						moves.add(new Move(r,c,r+1,c-1,false));
	
					}
					
				}
		
			}
	
			if(whosTurn == 2){
	
				//Check if valid move, not outside grid.
				if( ((r-1) >= 0)  && (c+1)  < size ){
					
					if( internalConfig[r-1][c+1] == 0){
						moves.add(new  Move(r,c,r-1,c+1,false));
					}
					
				}
				
				if( ((r-1) >= 0)  && (c-1)  >= 0){
					
					if( internalConfig[r-1][c-1] == 0){
						moves.add(new Move(r,c,r-1,c-1,false));
					}
					
				}
	
			}
		}
		
		
		return moves;
		
	}

	private ArrayList<Move> checkMultipleJumps(Move m,byte whosTurn, int size,ArrayList<Move> moveList, int pieceID){
		
		int r;
		int c;
		int lastr;
		int lastc;
		boolean dualMove = false;
		boolean topCheck = false;
		ArrayList<Move> tempList = m.getMoveList();
		if(tempList.size() > 0){
			 r = tempList.get(tempList.size()-1).getERow();
			 c = tempList.get(tempList.size()-1).getECol();
			 lastr = tempList.get(tempList.size()-1).getSRow();
		     lastc = tempList.get(tempList.size()-1).getSCol();
		} else {
			 topCheck = true;
			 r = m.getERow();
			 c = m.getECol();
			 lastr =  m.getSRow();
			 lastc =  m.getSCol();
		}

		 
		int oppoKing = -1;
		
		if( pieceID == 3){
			oppoKing = 4;
		} else if (pieceID == 4){
			oppoKing = 3;
		}

		//If you're a king of either type.
		if(oppoKing != -1){
			ArrayList<Integer> whichDirections = new ArrayList<Integer>(); 

			//Top-Left
			if( ((r-1) >= 0) && ((c-1) >= 0) && ((r-2) >= 0) && ((c-2) >= 0)){
				if( ((internalConfig[r-1][c-1] == oppoKing) || (internalConfig[r-1][c-1] == player)) && ((internalConfig[r-2][c-2] == 0))
						&& (r-2 != lastr || c-2 != lastc)){
					whichDirections.add(1);
				}
			}
			
			//Top-Right
			if( ((r-1) >= 0) && ((c+1) < size) && ((r-2) >= 0) && ((c+2) < size)){
				if( ((internalConfig[r-1][c+1] == oppoKing) || (internalConfig[r-1][c+1] == player)) && ((internalConfig[r-2][c+2] == 0))
						&& (r-2 != lastr || c+2 != lastc)){
					whichDirections.add(2);
				}
			}
			
			//Bot-Left
			if( ((r+1) < size) && ((c-1) >= 0) && ((r+2) < size) && ((c-2) >= 0)){
				if( ((internalConfig[r+1][c-1] == oppoKing) || (internalConfig[r+1][c-1] == player)) && ((internalConfig[r+2][c-2] == 0))
						&& (r+2 != lastr || c-2 != lastc)){
					whichDirections.add(3);
				}
			}
			
			//Bot-Right
			if( ((r+1) < size) && ((c+1) < size) && ((r+2) < size) && ((c+2) < size)){
				if( ((internalConfig[r+1][c+1] == oppoKing) || (internalConfig[r+1][c+1] == player)) && ((internalConfig[r+2][c+2] == 0))
						&& (r+2 != lastr || c+2 != lastc)){
					whichDirections.add(4);
				}
			}
			
			// If there is more than 1 location to jump to, create a new move for each other open jump.
			if(whichDirections.size() > 0){

				for(int i = 0; i < whichDirections.size(); i ++){

					if(whichDirections.get(i).intValue() == 1){
						if(i == 0){
							Move moveToAdd1 = new Move(r,c,r-2,c-2,r-1,c-1,true);
							m.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
						} else {
						
							Move newMove = new Move(m.getSRow(),m.getSCol(),m.getERow(),m.getECol(),m.getJRow(),m.getJCol(),true);
							Move moveToAdd1 = new Move(r,c,r-2,c-2,r-1,c-1,true);
							newMove.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(newMove,whosTurn,size,moveList,pieceID));
						}
						
						
					} else if(whichDirections.get(i).intValue() == 2){
						if(i == 0){
							Move moveToAdd1 = new Move(r,c,r-2,c+2,r-1,c+1,true);
							m.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
						}else {
							Move newMove = new Move(m.getSRow(),m.getSCol(),m.getERow(),m.getECol(),m.getJRow(),m.getJCol(),true);
							Move moveToAdd1 = new Move(r,c,r-2,c+2,r-1,c+1,true);
							newMove.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(newMove,whosTurn,size,moveList,pieceID));
						}
						
					}else if(whichDirections.get(i).intValue() == 3){
						if(i == 0){
							Move moveToAdd1 = new Move(r,c,r+2,c-2,r+1,c-1,true);
							m.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
						} else {
							Move newMove = new Move(m.getSRow(),m.getSCol(),m.getERow(),m.getECol(),m.getJRow(),m.getJCol(),true);
							Move moveToAdd1 = new Move(r,c,r+2,c-2,r+1,c-1,true);
							newMove.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(newMove,whosTurn,size,moveList,pieceID));
						}
					}else if(whichDirections.get(i).intValue() == 4){
						
						if(i == 0){
							Move moveToAdd1 = new Move(r,c,r+2,c+2,r+1,c+1,true);
							m.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
							
						} else {
							Move newMove = new Move(m.getSRow(),m.getSCol(),m.getERow(),m.getECol(),m.getJRow(),m.getJCol(),true);
							Move moveToAdd1 = new Move(r,c,r+2,c+2,r+1,c+1,true);
							newMove.addToList(moveToAdd1);
							moveList.addAll(checkMultipleJumps(newMove,whosTurn,size,moveList,pieceID));
						}
					}
	
				}

			}

		} else {

			//Add to columns if whosTurn == 1
			if(whosTurn == 1){
				
				//Check if valid move, not outside grid in both left and right diags. If this occurs, two new moves need to be created as they're seperate configs.
				if( ( ((r+1) < size) && ((r+2) < size) ) && ( ((c+1) < size) && ((c+2) < size))&& ((c-1) >= 0) && ((c-2) >= 0) && ( ((r+1) < size) && ((r+2) < size)) ){
				
						if( ((internalConfig[r+1][c+1] == player || internalConfig[r+1][c+1] == 4) && internalConfig[r+2][c+2] == 0) && ((internalConfig[r+1][c-1] == player ||
								internalConfig[r+1][c-1] == 4) && internalConfig[r+2][c-2] == 0)){
							Move moveToAdd1 = new Move(r,c,r+2,c+2,r+1,c+1,true);
							Move moveToAdd2 = new Move(r,c,r+2,c-2,r+1,c-1,true);
							Move newMove = new Move(m.getSRow(),m.getSCol(),m.getERow(),m.getECol(),m.getJRow(),m.getJCol(),true);
							
							m.addToList(moveToAdd1);
							newMove.addToList(moveToAdd2);
							
							moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
							moveList.addAll(checkMultipleJumps(newMove,whosTurn,size,moveList,pieceID));
							dualMove = true;
						}
				}
				if(( ((r+1) < size) && ((r+2) < size) ) && ( ((c+1) < size) && ((c+2) < size)) && !dualMove){
					
					if( ((internalConfig[r+1][c+1] == player || internalConfig[r+1][c+1] == 4) && internalConfig[r+2][c+2] == 0) ){
						Move moveToAdd1 = new Move(r,c,r+2,c+2,r+1,c+1,true);
						
						m.addToList(moveToAdd1);
						moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
					}
				}
				
				if(((c-1) >= 0) && ((c-2) >= 0) && ( ((r+1) < size) && ((r+2) < size)) && !dualMove){
					
					if( ((internalConfig[r+1][c-1] == player || internalConfig[r+1][c-1] == 4) && internalConfig[r+2][c-2] == 0) ){
						Move moveToAdd1 = new Move(r,c,r+2,c-2,r+1,c-1,true);
						
						m.addToList(moveToAdd1);
						moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
	
					}
				}
			}
			
			if(whosTurn == 2){
				
				if(( ((c+1) < size) && ((c+2) < size) ) && ( ((r-1) >= 0) && ((r-2) >= 0)) && ( ((r-1) >= 0) && ((r-2) >= 0) ) && ( ((c-1) >= 0) && ((c-2) >= 0)) ){
					
					if( ((internalConfig[r-1][c+1] == player || internalConfig[r-1][c+1] == 3)  && internalConfig[r-2][c+2] == 0) && ((internalConfig[r-1][c-1] == player || 
							internalConfig[r-1][c-1] == 3) && internalConfig[r-2][c-2] == 0)){
						Move moveToAdd1 = new Move(r,c,r-2,c+2,r-1,c+1,true);
						Move moveToAdd2 = new Move(r,c,r-2,c-2,r-1,c-1,true);
						Move newMove = new Move(m.getSRow(),m.getSCol(),m.getERow(),m.getECol(),m.getJRow(),m.getJCol(),true);
						
						m.addToList(moveToAdd1);
						newMove.addToList(moveToAdd2);
						
						moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
						moveList.addAll(checkMultipleJumps(newMove,whosTurn,size,moveList,pieceID));
						dualMove = true;
					}
					
				}
				 if( ( ((c+1) < size) && ((c+2) < size) ) && ( ((r-1) >= 0) && ((r-2) >= 0)) && !dualMove){
					
					if( ((internalConfig[r-1][c+1] == player || internalConfig[r-1][c+1] == 3) && internalConfig[r-2][c+2] == 0)){
						Move moveToAdd1 = new Move(r,c,r-2,c+2,r-1,c+1,true);
						m.addToList(moveToAdd1);
						moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
					}
				 }
					
				if( ( ((r-1) >= 0) && ((r-2) >= 0) ) && ( ((c-1) >= 0) && ((c-2) >= 0)) && !dualMove){
					
					if( ((internalConfig[r-1][c-1] == player || internalConfig[r-1][c-1] == 3) && internalConfig[r-2][c-2] == 0) ){
						Move moveToAdd1 = new Move(r,c,r-2,c-2,r-1,c-1,true);
						m.addToList(moveToAdd1);
						moveList.addAll(checkMultipleJumps(m,whosTurn,size,moveList,pieceID));
					}
				}
				
				
		
			}
		}
		if(!topCheck){
			ArrayList<Move> returnList = new ArrayList<Move>();
			returnList.add(m);
			return returnList;
		}
		return moveList;
		
	}
	
	private ArrayList<Move> checkJumps(int r, int c,byte whosTurn){
		ArrayList<Move> moves = new ArrayList<Move>();
		int size = internalConfig.length;
		int oppoKing = -1;
		int pieceID = internalConfig[r][c];
		if(pieceID == 3){
			oppoKing = 4;
		} else if (pieceID == 4){
			oppoKing = 3;
		}

		//If you're a king of either type.
		if(oppoKing != -1){
		
			//Check if valid move, not outside grid.
			if( ( ((r+1) < size) && ((r+2) < size) ) && ( ((c+1) < size) && ((c+2) < size)) ){

					if( ((internalConfig[r+1][c+1] == player || internalConfig[r+1][c+1] == oppoKing) && internalConfig[r+2][c+2] == 0) ){
						Move jump = new Move(r,c,r+2,c+2,r+1,c+1,true);
						ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
						if(multMoves.size() > 0 ){
							for(Move mJump : multMoves){
								moves.add(mJump);
							}
						} else{
							moves.add(jump);
						}
						

					}
			}
			
			//Check other direction
			if(	((c-1) >= 0) && ((c-2) >= 0) && ( ((r+1) < size) && ((r+2) < size)) ){
				
				if( ((internalConfig[r+1][c-1] == player || internalConfig[r+1][c-1] == oppoKing) && internalConfig[r+2][c-2] == 0) ){
					Move jump = new Move(r,c,r+2,c-2,r+1,c-1,true);
					ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
					if(multMoves.size() > 0 ){
						for(Move mJump : multMoves){
							moves.add(mJump);
						}
					} else{
						moves.add(jump);
					}
				
				
				}
			}
			
			
			if( ( ((c+1) < size) && ((c+2) < size) ) && ( ((r-1) >= 0) && ((r-2) >= 0)) ){
				
				if( ((internalConfig[r-1][c+1] == player || internalConfig[r-1][c+1] == oppoKing) && internalConfig[r-2][c+2] == 0) ){
					Move jump = new Move(r,c,r-2,c+2,r-1,c+1,true);
				
					ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
					if(multMoves.size() > 0 ){
						for(Move mJump : multMoves){
							moves.add(mJump);
						}
					} else{
						moves.add(jump);
					}
					
				}
			}
				
			if( ( ((r-1) >= 0) && ((r-2) >= 0) ) && ( ((c-1) >= 0) && ((c-2) >= 0)) ){
				
				if( ((internalConfig[r-1][c-1] == player  || internalConfig[r-1][c-1] == oppoKing) && internalConfig[r-2][c-2] == 0) ){
					Move jump = new Move(r,c,r-2,c-2,r-1,c-1,true);
					ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
					if(multMoves.size() > 0 ){
						for(Move mJump : multMoves){
							moves.add(mJump);
						}
					} else{
						moves.add(jump);
					}
				
				}
			}
			
		}else {

			//Add to columns if whosTurn == 1
			if(whosTurn == 1){
				
					//Check if valid move, not outside grid.
					if( ( ((r+1) < size) && ((r+2) < size) ) && ( ((c+1) < size) && ((c+2) < size)) ){
					
					
							if( ((internalConfig[r+1][c+1] == player || internalConfig[r+1][c+1] == 4) && internalConfig[r+2][c+2] == 0) ){
								Move jump = new Move(r,c,r+2,c+2,r+1,c+1,true);
								ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
								if(multMoves.size() > 0 ){
									for(Move mJump : multMoves){
										moves.add(mJump);
									}
								} else{
									moves.add(jump);
								}
								
		
							}
					}
					
					//Check other direction
					if(	((c-1) >= 0) && ((c-2) >= 0) && ( ((r+1) < size) && ((r+2) < size)) ){
						
						if( ((internalConfig[r+1][c-1] == player || internalConfig[r+1][c-1] == 4)&& internalConfig[r+2][c-2] == 0) ){
							Move jump = new Move(r,c,r+2,c-2,r+1,c-1,true);
							ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
							if(multMoves.size() > 0 ){
								for(Move mJump : multMoves){
									moves.add(mJump);
								}
							} else{
								moves.add(jump);
							}
						
						
						}
					}
				
			}
	
			//Subtract from columns if whosTurn == 2
			if(whosTurn == 2){
				
				//Check if valid move, not outside grid.
	
				if( ( ((c+1) < size) && ((c+2) < size) ) && ( ((r-1) >= 0) && ((r-2) >= 0)) ){
					
					if( ((internalConfig[r-1][c+1] == player || internalConfig[r-1][c+1] == 3) && internalConfig[r-2][c+2] == 0) ){
						Move jump = new Move(r,c,r-2,c+2,r-1,c+1,true);
					
						ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
						if(multMoves.size() > 0 ){
							for(Move mJump : multMoves){
								moves.add(mJump);
							}
						} else{
							moves.add(jump);
						}
						
					}
				}
					
				if( ( ((r-1) >= 0) && ((r-2) >= 0) ) && ( ((c-1) >= 0) && ((c-2) >= 0)) ){
					
					if( ((internalConfig[r-1][c-1] == player || internalConfig[r-1][c-1] == 3)&& internalConfig[r-2][c-2] == 0) ){
						Move jump = new Move(r,c,r-2,c-2,r-1,c-1,true);
						ArrayList<Move> multMoves = checkMultipleJumps(jump,whosTurn,size,new ArrayList<Move>(),pieceID);
						if(multMoves.size() > 0 ){
							for(Move mJump : multMoves){
								moves.add(mJump);
							}
						} else{
							moves.add(jump);
						}
					
					}
				}
			}	
		}

		//Still need to deal with kings and adding to the moves list.
		
		return moves;
	}
	
   /*
	public static void main(String[] args) {
		byte[][] testing = new byte[][] {
				{0,1,0,1,0,1,0,1},
				{1,2,0,2,1,0,1,0},
				{0,0,0,0,0,0,0,0},
				{0,0,0,4,0,2,0,0},
				{0,0,0,0,3,0,0,0},
				{0,0,0,2,0,1,0,0},
				{0,2,0,2,0,2,0,2},
				{2,0,2,0,2,0,2,0},
		};
		
		Config c = new Config(testing,2);
		Config c1 = null;
		System.out.println("STARTING CONFIG:");
		System.out.println(c);
		
	}
	*/
	
	
		
}
